import {deleteNull} from "../util";
import _ from 'lodash'
import db from '../util/db'
import Sequelize from 'sequelize'

const Op = Sequelize.Op
const cao_zuo_fu = { //操作符
    "==": Op["eq"],
    "!=": Op["ne"],
    ">=": Op["gte"],
    ">": Op["gt"],
    "<=": Op["lte"],
    "<": Op["lt"],
    "in": Op["in"],
    "like": Op["like"]
}
const cao_zuo_fu_revert = { //操作符
    [Op["eq"]]: "==",
    [Op["ne"]]: "!=",
    [Op["gte"]]: ">=",
    [Op["gt"]]: ">",
    [Op["lte"]]: "<=",
    [Op["lt"]]: "<",
    [Op["in"]]: "in",
    [Op["like"]]: "like"
}


export default class {
    model = null;
    options = {}
    leftJoinOptions = []
    leftJoinFeilds = []

    async add(payload, t) {
        var options = {}
        if (t) {
            options.transaction = t
        }
        return await this.model.create({
            ...payload
        }, options);
    }

    async remove(id) {
        return await this.model.destroy({
            where: {id}
        });
    }

    async update(id, payload, t) {
        var options = {}
        if (t) {
            options.t = t
        }
        delete payload.id
        return await this.model.update({...payload}, {
            where: {id}
        }, options);
    }

    async findById(id) {
        return await this.model.findOne({id});
    }


    /*
    * model.where({
        * name:{'>=':10},
        * name:{"like":"100"}
    * })
    * */
    where(options = {}) {
        delete options.limit
        delete options.from
        delete options.size
        this.options.where = Object.assign(this.options.where || {},
            this.adapterOption(options))
        return this
    }

    /*
    * var a={
    * age:{>=:b}
    * ,name:10}
    * */
    adapterOption(options) {
        _.map(options, (value, key) => {
            //需要在解
            if (value.constructor === Object) {
                var _key = Object.keys(value)[0]
                var _value = value[_key]
                var adapter_key = cao_zuo_fu[_key]
                var _result_value = _key === 'like' ? `%${_value}%` : _value
                value = {[adapter_key]: _result_value}
                options[key] = value
            }
        })
        return options
    }

    field(_filed = "*") {
        this.options.fields = _filed
        return this
    }

    leftJoin(tableName, sql, feilds) {
        if (!sql || !tableName || !feilds) return this
        if (!this.options.leftJoinOptions) {
            this.options.leftJoinOptions = []

        }
        if (!this.options.leftJoinFeilds) {
            this.options.leftJoinFeilds = []
        }
        this.options.leftJoinOptions = this.options.leftJoinOptions.concat(`left join "${tableName}" "${tableName}" on ${sql}`)
        this.options.leftJoinFeilds = this.options.leftJoinFeilds.concat(feilds)
        return this
    }

    page({from = 0, limit = 10}) {
        this.options = Object.assign(this.options,
            deleteNull({
                offset: from,
                limit
            })
        )
        return this
    }

    order(_array) {
        var __array = _array.constructor === Array ? __array : [__array]
        this.options.order = Object.assign(this.options.order, __array)
        return this
    }


    count() {//count不支持leftJoin
        var options = this.options
        delete options.limit
        delete options.offset
        this.options = {}
        return this.model.count(options)

    }

    /*
    * one true 就是只查一个*/
    select(options = {}, one = false) {
        var offset = options.from
        var limit = options.limit
        delete options.from
        delete options.limit
        var where = options.where
        this.options.where = Object.assign(this.options.where, this.adapterOption(options))
        if (offset) {
            this.options.offsets = offset
        }
        if (limit) {
            this.options.limit = limit
        }

        //如果是有 leftjoinOptions //开启sql查询
        if (this.options.leftJoinOptions && this.options.leftJoinOptions.length > 0) {
            var _sql = this.parseOption2sql(this.options)
            return this.selectBySql(_sql)
        }
        return this.afterSelect(this.options, one)
    }

    parseOption2sql() {
        /*
        * @result
        * select * from tablebame
        * left join leftjoinsql2
        * left join leftjoinsql1
        * order by 1,2,3,4
        * limit 0
        * offset 10
        * where wheresql
        * */
        var mainTableName = this.model.name
        var where = this.options.where
        var offset = this.options.offset
        var limit = this.options.limit
        var order = this.options.order
        var leftJoinOptions = this.options.leftJoinOptions
        var fields = this.options.fields
        var whereSql = ``;
        var leftJoinSql = ``;
        var feildSql = ``
        //create where sql
        _.map(where, (value, key) => {
            if (whereSql !== "") whereSql += " and" //每一个加上and
            var caoZuoFu = ""
            var _value = ""
            if (value.constructor === Object) {
                _.map(value, (__value, _caoZuoFu) => {
                    caoZuoFu = cao_zuo_fu_revert[_caoZuoFu]
                    _value = __value
                })
            } else {
                caoZuoFu = "="
                _value = value
            }
            whereSql += `"${mainTableName}".${key} ${caoZuoFu} ${_value}`
        })
        _.map(leftJoinOptions, value => {
            leftJoinSql += `${value} `
        })
        _.map(fields, (value) => {
            if (feildSql) feildSql += ", "
            feildSql = `"${mainTableName}"."${value}"`
        })
        if (feildSql === "") {
            feildSql = `"${mainTableName}".* `
        }
        _.map(this.options.leftJoinFeilds, (value) => {
            if (feildSql) feildSql += ", "
            feildSql += value + " "
        })
        var resultSql = `select ${feildSql} from "${mainTableName}" "${mainTableName}" 
${leftJoinSql}
${order ? "order by " + order.toString() : " "}
${offset ? "offset" + offset : " "}
${limit ? "limit" + limit : " "}
where ${whereSql}
`
        return resultSql


    }

    afterSelect(options, one = false) {
        this.options = {}
        console.log("lmt sqlOption====>", options)
        if (one) {
            return this.model.findOne(options)
        } else {
            return this.model.findAll(options)
        }

    }

    async selectBySql(sql) {
        this.options = {}
        var result = await db.query(sql).catch((e) => {
            console.error(e)
            return false
            // Results will be an empty array and metadata will contain the number of affected rows.
        })
        if (!result) return []
        var [results, metadata] = result
        return results
    }


}
